package br.usp.ime.dojo.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class DojoOnline implements EntryPoint, IdentificationListener, JoinARoomListener, ExitARoomListener, LogoutListener {
	private Identification identify;
	private VerticalPanel vPanel;
	private DojoRoomCreator roomCreator;
	private RoomListing roomListing;
	private RoomDisplay roomDisplay;
	private SessionDTO session;
	private UserDTO user;
	private IdentificationServiceAsync identificationService;
	private DojoMainMenu mainMenu;

	//TODO create a component to hold this data
	//private DojoRoomDTO dojoRoomDTO;
	//private UserDTO userDTO;
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {

		String sessionId = Cookies.getCookie("cookie");


		if(sessionId == null){
			displayIdentificationBox();
		}
		else{
			identificationService = GWT.create(IdentificationService.class);

			AsyncCallback<SessionDTO> callback = new AsyncCallback<SessionDTO>() {
				public void onFailure(Throwable caught) {
				}

				public void onSuccess(SessionDTO result) {
					session = result;
					if(session == null){
						displayIdentificationBox();
					}
					else if(session.getUserPlace().equals("DojoRoomCreator")){

						AsyncCallback<UserDTO> callback = new AsyncCallback<UserDTO>() {
							public void onFailure(Throwable caught) {
							}

							public void onSuccess(UserDTO result) {
								UserDTO loggedUser = result;
								onIdentificationSuccess(loggedUser);
							}
						};
						// Make the call to the identification service.
						identificationService.getUser(session.getUserName(), callback);
					}
					else{

						AsyncCallback<UserDTO> callback = new AsyncCallback<UserDTO>() {
							public void onFailure(Throwable caught) {
							}

							public void onSuccess(UserDTO result) {
								user = result;

								AsyncCallback<DojoRoomDTO> callback = new AsyncCallback<DojoRoomDTO>() {
									public void onFailure(Throwable caught) {
									}

									public void onSuccess(DojoRoomDTO result) {
										onJoinRequest(result);				
									}
								};
								
								identificationService.getRoom(session.getUserPlace(), callback);
								
							}
						};
						// Make the call to the identification service.
						identificationService.getUser(session.getUserName(), callback);

					}
				}
			};
			// Make the call to the identification service.
			identificationService.getSession(sessionId, callback);
		}

	}


	private void displayIdentificationBox() {
		identify = new Identification();
		identify.setIdentificationListener(this);
		if(vPanel == null)
			setInterface();
		vPanel.add(identify);
	}


	public void setInterface() {
		vPanel = new VerticalPanel();
		vPanel.setWidth("100%");
		vPanel.setHeight("100%");
		vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
		vPanel.setHeight("100%");

		RootPanel.get("dojoMain").setWidth("90%");
		RootPanel.get("dojoMain").add(vPanel);
		RootPanel.get("dojoMain").addStyleName("dojoMainMenu");
		
	}

	public void onExitDojoRoom(){
		
		if(vPanel == null)setInterface();
		
		if(roomDisplay != null) {			
			vPanel.remove(roomDisplay);
			roomDisplay = null;
		}

		
		SessionDTO sessionDTO = new SessionDTO(user.getName(),"DojoRoomCreator");
		identificationService.addSession(sessionDTO, new AsyncCallback<String>(){
			public void onFailure(Throwable caught) {
			}
			public void onSuccess(String result) {
				Cookies.setCookie("cookie", result);
				displayDojoRoomCreator(user);
			}
		});
		
	}

	public void onIdentificationSuccess(UserDTO loggedUser) {
		user = loggedUser;
		if(identify != null)
			vPanel.remove(identify);

		mainMenu = new DojoMainMenu();
		RootPanel.get("dojoMainMenu").add(mainMenu);
		RootPanel.get("dojoMainMenu").addStyleName("dojoMainMenu");
		mainMenu.onIdentificationSuccess(user.getName());
		mainMenu.setLogoutListener(this);

		if(identificationService == null)
			identificationService = GWT.create(IdentificationService.class);

		
		SessionDTO sessionDTO = new SessionDTO(loggedUser.getName(),"DojoRoomCreator");
		identificationService.addSession(sessionDTO, new AsyncCallback<String>(){
			public void onFailure(Throwable caught) {
			}
			public void onSuccess(String result) {
				Cookies.setCookie("cookie", result);
				displayDojoRoomCreator(user);
			}
		});
	}

	public void onJoinRequest(DojoRoomDTO room) {
		if(vPanel == null)
			setInterface();
		
		if(roomCreator != null)
			vPanel.remove(roomCreator);
		if(roomListing != null)
			vPanel.remove(roomListing);
				
		if(roomDisplay == null)
			roomDisplay = new RoomDisplay(room, user);
		
		if(mainMenu == null) {
			mainMenu = new DojoMainMenu();
			RootPanel.get("dojoMainMenu").add(mainMenu);
			RootPanel.get("dojoMainMenu").addStyleName("dojoMainMenu");
			mainMenu.onIdentificationSuccess(user.getName());
			mainMenu.setLogoutListener(this);
		}
		
		SessionDTO sessionDTO = new SessionDTO(user.getName(),room.getName());
		identificationService.addSession(sessionDTO, new AsyncCallback<String>(){
			public void onFailure(Throwable caught) {
			}
			public void onSuccess(String result) {
				Cookies.setCookie("cookie", result);
			}
		});
		
		roomDisplay.setExitADojoRoomListener(this);
		vPanel.add(roomDisplay);
	}


	private void displayDojoRoomCreator(UserDTO loggedUser) {
		if(vPanel == null){
			setInterface();
		}

		if(roomCreator == null){
			roomCreator = new DojoRoomCreator(loggedUser.getName());
		}
		if(roomListing == null){
			roomListing = new RoomListing();
		}

		roomListing.setJoinRequestListener(this);
		roomCreator.setJoinRequestListener(this);
		vPanel.add(roomListing);
		vPanel.add(roomCreator);
	}



	public void onLogout() {
		if(roomDisplay != null){
			roomDisplay.exitUserFromRoom();
			roomDisplay = null;
		}
		identificationService.removeUser(user.getName(),new AsyncCallback<Void>(){

			public void onFailure(Throwable caught) {
			}
			public void onSuccess(Void result) {
				Cookies.removeCookie("cookie");
				destroyAll();
				displayIdentificationBox();
			}
			
		});
	}


	private void destroyAll() {
		if(vPanel != null){
			vPanel.clear();
		}
		if(roomDisplay != null){
			roomDisplay.exitUserFromRoom();
			roomDisplay = null;
		}
		
		identify = null;
		roomCreator = null;
		roomListing = null;
		session = null;
		user = null;
		
		if(mainMenu != null)
			mainMenu.setVisible(false);
	}
}
